#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <grpcpp/grpcpp.h>
#include "../protos/{{ service_name| lower }}.grpc.pb.h"
#include "../atomic_include/{{ service_name|lower }}.h"
#include "../../../../include/log_client/LogClient.h"

class {{ service_name_service }}_ServerImpl final : public ::{{service_name_package}}::{{ service_name_service }}::Service {
public:
    {{ service_name_service }}_ServerImpl() {
        LogClient::getInstance().init("{{service_name_service}}", "{{service_name_service}}");
    } 
    {% for method in methods %}
    ::grpc::Status {{ method._name }}(::grpc::ServerContext* context, 
            const ::{{service_name_package}}::{{ method._requestMsg._name }}* request, 
                ::{{service_name_package}}::{{ method._responseMsg._name }}* reply) override {

        {{service_name}}::{{ method._requestMsg._name }} {{ service_name }}_Request_t;
        {{service_name}}::{{ method._responseMsg._name }} {{ service_name }}_Reply_t;

        {% for field in  method._requestMsg._fields %}
        {% if field._repeated == true %}
        for(int i=0; i < request->{{field._name}}_size();++i){
            {{ service_name }}_Request_t.{{field._name}}.push_back(request->{{field._name}}(i));
        }
        {% elif field._map == true %}
        for (const auto& item : request->{{field._name}}()) {
            {{ service_name }}_Request_t.{{field._name}}[item.first] = item.second;
        }
        {% else %}
        {{ service_name }}_Request_t.{{field._name}} = request->{{field._name}}();
        {% endif %}
        {% endfor %}

        /******************************************************************/
        {{service_name}}::{{ method._name }}(&{{ service_name }}_Request_t, &{{ service_name }}_Reply_t);

        /******************************************************************/

        reply->Clear(); // clear reply message
        {% for field in  method._responseMsg._fields %}
        {% if field._repeated == true %}
        for(int i=0; i < {{ service_name }}_Reply_t.{{field._name}}.size(); ++i){
            reply->mutable_{{field._name}}()->Add({{ service_name }}_Reply_t.{{field._name}}[i]);
        }
        {% elif field._map == true %}
        for (const auto& item : {{ service_name }}_Reply_t.{{field._name}}) {
            reply->mutable_{{field._name}}()->insert({item.first, item.second});
        }
        {% else %}
        reply->set_{{field._name}}({{ service_name }}_Reply_t.{{field._name}});
        {% endif %}
        {% endfor %}
        std::string info = "This is Method = {{ method._name }},   ServiceName = {{ service_name_service }}\n";
        std::cout << info << std::endl;
        info = info + {{service_name}}::toString({{ service_name }}_Request_t) + "\n";
        info = info + {{service_name}}::toString({{ service_name }}_Reply_t) + "\n";
        LogClient::getInstance().logInfo("{{service_name}}", "{{service_name}}", info);
        return grpc::Status::OK;
    }

    {% endfor %}
};